﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DAL
{
    public partial class EstructuraCostoItem : ICloneable
    {

        public decimal getMontoTotalDivision(dbGestionDataContext _db)
        {
            decimal result = 0;
            //suma de tolos los hijos

            var q = (from i in _db.EstructuraCostoItems
                     where i.idPadre == this.idInternal 
                     select i);

            if (q.Count() > 0)
            { 
                result = q.Sum(p => p.total).Value;
            }

            return Math.Round(result, 2);
        }


        public decimal getMontoUsoTotalComparativoItem(dbGestionDataContext _db, int idECItem)
        {
            decimal result = 0;
            //estado 3 es Aprobado2

            var q = (from i in _db.ComparativoItemSelecPrv
                     where i.ComparativoItem.idEstructuraCostoItem == idECItem
                      & (i.ComparativoItem.Comparativo.idEstado > 2| i.cantidadUso>0)
                     select (i.totalUso == 0 |i.ComparativoItem.Comparativo.idEstado > 2) ? i.total*i.ComparativoItem.tipoCambio : i.totalUso*i.ComparativoItem.tipoCambio);
            //Importante el tipo de cambio
            // lo tomo d
            
            if (q.Count() > 0)  
            {
                // se estable en soles

                result = q.Sum().Value;
            }
            //devuleve de acuerdo a la moneda Base soles
            return Math.Round(result, 4);
        }

        public decimal getCantidadUsoTotalComparativoItem(dbGestionDataContext _db, int idECItem)
        {
            decimal result = 0;

            var q = (from i in _db.ComparativoItemSelecPrv
                     where i.ComparativoItem.idEstructuraCostoItem == idECItem
                       & (i.ComparativoItem.Comparativo.idEstado > 2 | i.cantidadUso > 0)
                     select (i.cantidadUso == 0) ? i.cantidad : i.cantidadUso);

            if (q.Count() > 0)
            {
                result = q.Sum().Value;
            }

            return result;
        }


        public decimal getMontoTotalComparativoItem(dbGestionDataContext _db, int idECItem)
        {
            decimal result = 0;
            //estado 3 es Aprobado2
            // el comparativo solo un proveedor
            //solo actualizo si es mayor

            var q = (from i in _db.ComparativoItemSelecPrv
                     where i.ComparativoItem.idEstructuraCostoItem == idECItem

                     select i);
            //Importante el tipo de cambio
            // lo tomo d

            if (q.Count() > 0)
            {
                // se estable en soles
                result = q.Sum(p => (p.total * p.ComparativoItem.tipoCambio)).Value;
            }
            //devuleve de acuerdo a la moneda Base soles
            return result;
        }

        public decimal getCantidadTotalComparativoItem(dbGestionDataContext _db, int idECItem)
        {
            decimal result = 0;
            //solo actualizo si es mayor
            

            var q = (from i in _db.ComparativoItemSelecPrv
                     where i.ComparativoItem.idEstructuraCostoItem == idECItem

                     select i);
            
            

            if (q.Count() > 0 )
            {
                if (this.unidad.ToUpper() != "GLB")
                {
                    result = q.Sum(p => p.cantidad).Value;
                }
                else
                {
                    result = 1;
                }
                
            }

            return result;
        }




        public bool updateMontoDivisionItemPadre(dbGestionDataContext _db)
        {

         //este objeto es el padre

           this.total =this.getMontoTotalDivision(_db);
                       

            if (this.total == 0)
            {
                ///eliminamos el padre para que cuadre con lo que se tiene en el recurso
                _db.EstructuraCostoItems.DeleteOnSubmit(this);
            }else
            
            {
                // si es global por la cantidad
                if (this.unidad.ToUpper() == "GLB")
                {
                    this.precio = this.total / this.cantidad;
                }
                else
                {
                    this.cantidad = this.total / this.precio;
                }
                
                
            }
            _db.SubmitChanges();
                return true;

        }

        public void updateJuntarPadre(dbGestionDataContext _db,int idJuntarPadre)
        {
            this.idJuntoPadre = idJuntarPadre;
            this.fechaMod = DateTime.Now;
            this.bitsel = false;
            _db.SubmitChanges();
        }


        public void setMonedaYTCFromRecurso(dbGestionDataContext _db, int idRecurso)
        {
             Recurso dbRecurso = _db.Recursos.Single(p => p.idInternal == idRecurso);
           Presupuesto dbpresu=dbRecurso.Partida.Presupuesto;
           Obra obra = _db.Obras.Single(p => p.idInternal == dbpresu.idObra);
            
            this.idMoneda = dbpresu.idMoneda;
            
            if (this.idMoneda == 4)
            {
                //tipo cambio en dolares 
                this.tipoCambio = obra.tipoCambio;
            }
            else
            {
                // solo en tipo contrato es en dolares los demas obtamos en soloes 
                this.tipoCambio = 1;
            }
            

        }
        
        /// <summary>
        /// Para el caso de la Estructura de Costos de agrupado, no se tiene el tipo de cambio que utilizar por ello se 
        /// mantiene por default tipo de cambio del contrato,
        /// </summary>
        /// <param name="_db"></param>
        /// <param name="idMoneda"></param>
        /// <param name="idObra"></param>
        public void setTCFromMoneda(dbGestionDataContext _db, int idMoneda, int idObra)
        {

            Obra obra = _db.Obras.Single(p => p.idInternal == idObra);
            this.idMoneda = idMoneda;

            if (idMoneda == 4)
            {
                //tipo cambio en dolares 
                this.tipoCambio = obra.tipoCambio.Value;
            }
            else
            {
                // solo en tipo contrato es en dolares los demas obtamos en soloes 
                this.tipoCambio = 1;
            }


        }
        public int addECItemFromRecurso(dbGestionDataContext _db,
                                            int idEstructuraCosto, 
                                            Recurso dbRecurso,
                                            int  idEmpleado)
                                        {
            decimal cantidad=  dbRecurso.cantidad.Value - dbRecurso.cantidadUso.Value; 
            decimal total=  dbRecurso.parcial.Value - dbRecurso.parcialUso.Value;       
         //todos los de nivel cero no tiene padre

            this.addECItem(_db,
                                        idEstructuraCosto,
                                        dbRecurso.idInternal,
                                        dbRecurso.idInsumo.Value,
                                        dbRecurso.codigo,
                                        dbRecurso.descripcion,
                                        dbRecurso.unidad,
                                        0,
                                        null,
                                        true,
                                        cantidad,
                                        dbRecurso.precio.Value,
                                        total,
                                        null,
                                        null,
                                        null,
                                        idEmpleado,
                                        null);
                   
            return this.idInternal;
        }
        public int addECItem(dbGestionDataContext _db, 
                                int idEstructuraCosto, 
                                int? idRecurso,
                                int idInsumo,
                                string  codigo,
                                string descripcion,
                                string  unidad,
                                short nivel,
                                int? idPadre,
                                bool bitSel,
                                decimal cantidad,
                                decimal precio,
                                decimal total,
                                int? idmoneda,
                                    decimal? tipoCambio,
                                int? idAgrupadoFin,
                                int usuarioCre ,
                                int? idOrdenCompraItemRef)
        {

            this.idEstructuraCosto = idEstructuraCosto;
            this.idInsumo = idInsumo;
            this.idRecurso = idRecurso;
            this.codigo = codigo;
            this.descripcion = descripcion;
            this.unidad = unidad;
            this.nivel = nivel;
            this.bitsel =bitSel;
            this.idPadre = idPadre;
            this.cantidad = cantidad;
            this.precio = precio;
            this.total = total;
            this.usuarioCre = usuarioCre;
            this.idAgrupadoDestino = idAgrupadoFin;
            this.fechaCre = DateTime.Now;
            this.fechaMod = DateTime.Now;
            this.usuarioMod = usuarioCre;
            this.totalReUso = 0;
            this.idOrdenCompraItemRef = idOrdenCompraItemRef;

            if (idRecurso != null)
            {
                this.setMonedaYTCFromRecurso(_db, idRecurso.Value);
            }
            else
            {
                //debe ser ingresado
                this.idMoneda = idmoneda.Value;
                this.tipoCambio = tipoCambio.Value;
            }

            this.totalMonBase = this.total * this.tipoCambio;
            this.cantidadUso = 0;
            this.totalUso = 0;
            this.totalReUso = 0;


            _db.EstructuraCostoItems.InsertOnSubmit(this);

            _db.SubmitChanges();


            return this.idInternal;
        }


        public  void updateUso(dbGestionDataContext _db)
        {
            

            
            this.cantidadUso=this.getCantidadUsoTotalComparativoItem(_db, this.idInternal);
            
            // este total es segun la moneda Base soles con el tP del comparativo
            
            decimal totalUso = this.getMontoUsoTotalComparativoItem(_db, this.idInternal);
            
            if (totalUso > 0)
            {
                // actualizo segun la moneda del recurso 27052010
                this.totalUso = totalUso / this.tipoCambio;
            }
            else
            {
                this.bitControlCant = null;
                this.totalUso = totalUso;
            }



            _db.SubmitChanges();

        }

        public void updateBaseFromComparativo(dbGestionDataContext _db, int idUsuario,int idComparativoItem)
        {

            //solo debe actualizar cuando es finalizado
            decimal cantidadcomparativo=    this.getCantidadTotalComparativoItem(_db, this.idInternal);

            int idEmpleadoEmisor = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());

            decimal cantidadSobrante = 0;
            
            if (this.unidad.ToUpper() != "GLB")
            {
                cantidadSobrante = this.cantidad.Value -cantidadcomparativo;
                                        
            }
            else
            {
                cantidadSobrante = 1;
            }
            if (cantidadSobrante > 0 & this.unidad.ToUpper() != "GLB")
            {
                this.cantidad = cantidadcomparativo;
            }
            // este total es segun la moneda Base soles con el tP del comparativo
           // viene en soles 
            decimal totalComparativo = this.getMontoTotalComparativoItem(_db, this.idInternal);
            totalComparativo = totalComparativo / this.tipoCambio.Value;
            decimal totalsobrante = this.total.Value - totalComparativo;

                //para la cantidad//

                if (totalsobrante>0)
                {
                    this.total = totalComparativo;
                    //la diferencia si es mayor se crear otro registro

            EstructuraCostoItem nuevo= new EstructuraCostoItem();
                        nuevo.addECItem(_db,
                            this.idEstructuraCosto.Value,
                            null,
                            this.idInsumo.Value,
                            this.codigo,
                            this.descripcion,
                            this.unidad,
                            0,
                            null,
                            this.bitsel.Value,
                            cantidadSobrante,
                            this.precio.Value,
                            totalsobrante,
                            this.idMoneda,
                            this.tipoCambio,
                            null,
                            idEmpleadoEmisor,
                            null);
                        nuevo.ComparativoItemRef = idComparativoItem;

                
                    }
            
            _db.SubmitChanges();

        }

        public bool updatePadreDetallado(dbGestionDataContext _db,int idUsuario)
        {
            // verifico los hijos  y verifico si es global
            this.fechaMod = DateTime.Now;
            this.usuarioMod = idUsuario;
            this.total = this.getMontoTotalDivision(_db);
            
            if (this.unidad.ToUpper() != "GLB")
            {
                this.cantidad = Math.Round(this.total.Value / this.precio.Value,4);
            }
            else
            {
                // para los casos de global  la cantidad es 1, por
                // cada division.

                this.cantidad = 0;
                if (this.total > 0)
                {
                    this.cantidad= 1;
                }
            }

            _db.SubmitChanges();
            return true;



        }

        public void SetOrdenCompraRef(int? idOrdenCompraitem)
        {
            this.idOrdenCompraItemRef = idOrdenCompraitem;
        }

        public object Clone()
        {


            return MemberwiseClone(); ;

        } 
    }
}
